home *** CD-ROM | disk | FTP | other *** search
/ GFX Sensations 1 / Graphic Sensations - Volume 1.iso / tools / amiga / 3d_tools / irit40s.lha / Irit / cagd_lib / cagdsmrg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-30  |  8.1 KB  |  256 lines

  1. /******************************************************************************
  2. * CagdCMrg.c - Surface/Surface merging routine.                      *
  3. *******************************************************************************
  4. * Written by Gershon Elber, Sep 92.                          *
  5. ******************************************************************************/
  6.  
  7. #include "cagd_loc.h"
  8.  
  9. static void InterpolateLinearSeg(CagdRType *V1, CagdRType *V2, int Len,
  10.                                 int Step);
  11.  
  12. /******************************************************************************
  13. * Merge two surfaces in the provided direction Dir. If SameEdge, it is        *
  14. * assumed last edge of Srf1 is identical to first edge of Srf2 and one row    *
  15. * is dropped from new mesh. Otherwise a ruled surface is fit between the two  *
  16. * edges.                                      *
  17. ******************************************************************************/
  18. CagdSrfStruct *CagdMergeSrfSrf(CagdSrfStruct *Srf1, CagdSrfStruct *Srf2,
  19.                    CagdSrfDirType Dir, CagdBType SameEdge)
  20. {
  21.     CagdBType IsNotRational;
  22.     int i, j, UOrder, VOrder, ULen1, VLen1, ULen2, VLen2, MaxCoord, Length;
  23.     CagdRType **Points1, **Points2, **Points;
  24.     CagdPointType SrfPType;
  25.     CagdSrfStruct *Srf;
  26.  
  27.     /* Make surfaces compatible: */
  28.     Srf1 = CagdSrfCopy(Srf1);
  29.     Srf2 = CagdSrfCopy(Srf2);
  30.  
  31.     switch (Dir) {
  32.     case CAGD_CONST_U_DIR:
  33.     case CAGD_CONST_V_DIR:
  34.         if (!CagdMakeSrfsCompatible(&Srf1, &Srf2, TRUE, TRUE,
  35.                     Dir == CAGD_CONST_V_DIR,
  36.                     Dir == CAGD_CONST_U_DIR))
  37.         FATAL_ERROR(CAGD_ERR_SRF_FAIL_CMPT);
  38.         break;
  39.     default:
  40.         FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  41.         break;
  42.     }
  43.  
  44.     /* Verify surface geometric types. */
  45.     switch (Srf1 -> GType) {
  46.     case CAGD_SBEZIER_TYPE:
  47.         Srf = CnvrtBezier2BsplineSrf(Srf1);
  48.         CagdSrfFree(Srf1);
  49.         Srf1 = Srf;
  50.         Srf = CnvrtBezier2BsplineSrf(Srf2);
  51.         CagdSrfFree(Srf2);
  52.         Srf2 = Srf;
  53.         break;
  54.     case CAGD_SBSPLINE_TYPE:
  55.         break;
  56.     case CAGD_SPOWER_TYPE:
  57.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  58.         break;
  59.     default:
  60.         FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
  61.         break;
  62.     }
  63.  
  64.     UOrder = Srf1 -> UOrder;
  65.     VOrder = Srf1 -> VOrder;
  66.     ULen1 = Srf1 -> ULength;
  67.     VLen1 = Srf1 -> VLength;
  68.     ULen2 = Srf2 -> ULength;
  69.     VLen2 = Srf2 -> VLength;
  70.     Points1 = Srf1 -> Points;
  71.     Points2 = Srf2 -> Points;
  72.     IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf1);
  73.     MaxCoord = CAGD_NUM_OF_PT_COORD(Srf1 -> PType),
  74.     SrfPType = CAGD_MAKE_PT_TYPE(!IsNotRational, MaxCoord);
  75.  
  76.     switch (Dir) {
  77.     case CAGD_CONST_U_DIR:
  78.         Length = SameEdge ? ULen1 + ULen2 - 1 : ULen1 + ULen2 + UOrder - 2;
  79.         Srf = BspSrfNew(Length, VLen1, UOrder, VOrder, SrfPType);
  80.  
  81.         /* Update knot vectors. We assume open end condition here... */
  82.         CAGD_GEN_COPY(Srf -> UKnotVector, Srf1 -> UKnotVector,
  83.               (ULen1 + UOrder - 1) * sizeof(CagdRType));
  84.         CAGD_GEN_COPY(Srf -> VKnotVector, Srf1 -> VKnotVector,
  85.               (VLen1 + VOrder) * sizeof(CagdRType));
  86.  
  87.         if (SameEdge) {
  88.         /* Copy kv of second surface immediately after. */
  89.         CAGD_GEN_COPY(&Srf -> UKnotVector[ULen1 + UOrder - 1],
  90.                   &Srf2 -> UKnotVector[UOrder],
  91.                   ULen2 * sizeof(CagdRType));
  92.         BspKnotAffineTrans(&Srf -> UKnotVector[ULen1 + UOrder - 1],
  93.                    ULen2,
  94.                    Srf -> UKnotVector[ULen1 + UOrder - 2] -
  95.                    Srf2 -> UKnotVector[0],
  96.                    1.0);
  97.         }
  98.         else {
  99.         /* Copy kv of second surface order after. */
  100.         CAGD_GEN_COPY(&Srf -> UKnotVector[ULen1 + UOrder - 1],
  101.                   &Srf2 -> UKnotVector[1],
  102.                   (ULen2 + UOrder - 1) * sizeof(CagdRType));
  103.         BspKnotAffineTrans(&Srf -> UKnotVector[ULen1 + UOrder - 1],
  104.                    ULen2 + UOrder - 1,
  105.                    Srf -> UKnotVector[ULen1 + UOrder - 2] -
  106.                    Srf -> UKnotVector[ULen1 + UOrder - 1] + 1.0,
  107.                    1.0);
  108.         }
  109.  
  110.         Points = Srf -> Points;
  111.  
  112.         for (i = 0; i < VLen1; i++) {
  113.         for (j = IsNotRational; j <= MaxCoord; j++) {
  114.             CAGD_GEN_COPY(&Points[j][CAGD_MESH_UV(Srf, 0, i)],
  115.                   &Points1[j][CAGD_MESH_UV(Srf1, 0, i)],
  116.                   ULen1 * sizeof(CagdRType));
  117.             if (SameEdge) {
  118.             /* Copy row of second surface immediately after. */
  119.             CAGD_GEN_COPY(
  120.                 &Points[j][CAGD_MESH_UV(Srf, ULen1 - 1, i)],
  121.                 &Points2[j][CAGD_MESH_UV(Srf2, 0, i)],
  122.                 ULen2 * sizeof(CagdRType));
  123.             }
  124.             else {
  125.             /* Copy row of 2nd srf order after and lin. interp. */
  126.             CAGD_GEN_COPY(
  127.                 &Points[j][CAGD_MESH_UV(Srf, ULen1 + UOrder - 2, i)],
  128.                 &Points2[j][CAGD_MESH_UV(Srf2, 0, i)],
  129.                 ULen2 * sizeof(CagdRType));
  130.             InterpolateLinearSeg(
  131.                 &Points[j][CAGD_MESH_UV(Srf, ULen1 - 1, i)],
  132.                 &Points[j][CAGD_MESH_UV(Srf, ULen1 + UOrder - 2, i)],
  133.                 UOrder, 1);
  134.             }
  135.         }
  136.         }
  137.         break;
  138.     case CAGD_CONST_V_DIR:
  139.         Length = SameEdge ? VLen1 + VLen2 - 1 : VLen1 + VLen2 + VOrder - 2;
  140.         Srf = BspSrfNew(ULen1, Length, UOrder, VOrder, SrfPType);
  141.  
  142.         /* Update knot vectors. We assume open end condition here... */
  143.         CAGD_GEN_COPY(Srf -> UKnotVector, Srf1 -> UKnotVector,
  144.               (ULen1 + UOrder) * sizeof(CagdRType));
  145.         CAGD_GEN_COPY(Srf -> VKnotVector, Srf1 -> VKnotVector,
  146.               (VLen1 + VOrder - 1) * sizeof(CagdRType));
  147.  
  148.         if (SameEdge) {
  149.         /* Copy kv of second surface immediately after. */
  150.         CAGD_GEN_COPY(&Srf -> VKnotVector[VLen1 + VOrder - 1],
  151.                   &Srf2 -> VKnotVector[VOrder],
  152.                   VLen2 * sizeof(CagdRType));
  153.         BspKnotAffineTrans(&Srf -> VKnotVector[VLen1 + VOrder - 1],
  154.                    VLen2,
  155.                    Srf -> VKnotVector[VLen1 + VOrder - 2] -
  156.                    Srf2 -> VKnotVector[0],
  157.                    1.0);
  158.         }
  159.         else {
  160.         /* Copy kv of second surface order after. */
  161.         CAGD_GEN_COPY(&Srf -> VKnotVector[VLen1 + VOrder - 1],
  162.                   &Srf2 -> VKnotVector[1],
  163.                   (VLen2 + VOrder - 1) * sizeof(CagdRType));
  164.         BspKnotAffineTrans(&Srf -> VKnotVector[VLen1 + VOrder - 1],
  165.                    VLen2 + VOrder - 1,
  166.                    Srf -> VKnotVector[VLen1 + VOrder - 2] -
  167.                    Srf -> VKnotVector[VLen1 + VOrder - 1] + 1.0,
  168.                    1.0);
  169.         }
  170.  
  171.         Points = Srf -> Points;
  172.  
  173.         for (i = 0; i < ULen1; i++) {
  174.         for (j = IsNotRational; j <= MaxCoord; j++) {
  175.             CAGD_GEN_COPY_STEP(&Points[j][CAGD_MESH_UV(Srf, i, 0)],
  176.                        &Points1[j][CAGD_MESH_UV(Srf1, i, 0)],
  177.                        VLen1, ULen1, ULen1, CagdRType);
  178.             if (SameEdge) {
  179.             /* Copy col of second surface immediately after. */
  180.             CAGD_GEN_COPY_STEP(
  181.                 &Points[j][CAGD_MESH_UV(Srf, i, VLen1 - 1)],
  182.                 &Points2[j][CAGD_MESH_UV(Srf2, i, 0)],
  183.                 VLen2, ULen1, ULen1, CagdRType);
  184.             }
  185.             else {
  186.             /* Copy col of 2nd srf order after and lin. interp. */
  187.             CAGD_GEN_COPY_STEP(
  188.                 &Points[j][CAGD_MESH_UV(Srf, i, VLen1 + VOrder - 2)],
  189.                 &Points2[j][CAGD_MESH_UV(Srf2, i, 0)],
  190.                 VLen2, ULen1, ULen1, CagdRType);
  191.             InterpolateLinearSeg(
  192.                 &Points[j][CAGD_MESH_UV(Srf, i, VLen1 - 1)],
  193.                 &Points[j][CAGD_MESH_UV(Srf, i, VLen1 + VOrder - 2)],
  194.                 VOrder, ULen1);
  195.             }
  196.         }
  197.         }
  198.         break;
  199.     default:
  200.         Srf = NULL;
  201.         FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  202.         break;
  203.     }
  204.  
  205.     CagdSrfFree(Srf1);
  206.     CagdSrfFree(Srf2);
  207.  
  208.     return Srf;
  209. }
  210.  
  211. /******************************************************************************
  212. * Merge a list of surfaces, in order.                          *
  213. ******************************************************************************/
  214. CagdSrfStruct *CagdMergeSrfList(CagdSrfStruct *SrfList, CagdSrfDirType Dir,
  215.                             CagdBType SameEdge)
  216. {
  217.     if (SrfList != NULL && SrfList -> Pnext != NULL) {
  218.     CagdSrfStruct
  219.         *MergedSrf = CagdSrfCopy(SrfList);
  220.  
  221.     for (SrfList = SrfList -> Pnext;
  222.          SrfList != NULL;
  223.          SrfList = SrfList -> Pnext) {
  224.         CagdSrfStruct
  225.         *TmpSrf = CagdMergeSrfSrf(MergedSrf, SrfList, Dir, SameEdge);
  226.  
  227.         CagdSrfFree(MergedSrf);
  228.         MergedSrf = TmpSrf;
  229.     }
  230.     return MergedSrf;
  231.     }
  232.     else
  233.     return SrfList ? CagdSrfCopy(SrfList) : NULL;
  234. }
  235.  
  236. /******************************************************************************
  237. * Linearly interpolate between V1 and V2 values Len times (Len includes V1    *
  238. * and V2) and step the array using Step.                      *
  239. ******************************************************************************/
  240. static void InterpolateLinearSeg(CagdRType *V1, CagdRType *V2, int Len,
  241.                                 int Step)
  242. {
  243.     int i;
  244.     CagdRType
  245.     *V = V1 + Step;
  246.  
  247.     if (Len-- <= 2)
  248.     return;                     /* No middle points to interp. */
  249.  
  250.     for (i = 1; i < Len; i++) {
  251.     *V = (i * (*V2) + (Len - i) * (*V1)) / Len;
  252.  
  253.     V += Step;
  254.     }
  255. }
  256.